package com.oig.sys.workflow.service.impl;

import cn.hutool.core.util.StrUtil;
import com.oig.common.constants.CommonEnum;
import com.oig.common.exception.BadRequestException;
import com.oig.common.module.SysRequest;
import com.oig.sys.workflow.dao.ITbDataModuleDao;
import com.oig.sys.workflow.dto.DataModuleDto;
import com.oig.sys.workflow.entity.TbDataModule;
import com.oig.sys.workflow.service.ITbDataModuleDetailService;
import com.oig.sys.workflow.service.ITbDataModuleService;
import com.oig.sys.workflow.vo.DataModuleDetailVo;
import com.oig.sys.workflow.vo.DataModuleVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;

/**
 * @author wuxl
 */
@Service
public class TbDataModuleServiceImpl implements ITbDataModuleService {

	private final ITbDataModuleDao tbDataModuleDao;
	private final ITbDataModuleDetailService dataModuleDetailService;

	@Autowired
	public TbDataModuleServiceImpl(ITbDataModuleDao tbDataModuleDao,
								   ITbDataModuleDetailService dataModuleDetailService){
		 this.tbDataModuleDao = tbDataModuleDao;
		 this.dataModuleDetailService = dataModuleDetailService;
	}

	@Transactional
	@Override
	public DataModuleVo addDataModule(DataModuleDto dataModuleDto){
		TbDataModule dataModule = this.tbDataModuleDao.getByTableName(dataModuleDto.getTableName()) ;
		if (dataModule!=null){
			throw new BadRequestException("tableName重复");
		}
		dataModule = new TbDataModule();
		BeanUtils.copyProperties(dataModuleDto, dataModule,"id");
		dataModule.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
		this.tbDataModuleDao.save(dataModule);
		List<DataModuleDetailVo> detailVoList=dataModuleDetailService.addDataModuleDetailList(dataModule.getId(),dataModuleDto.getDataModuleDetailDtoList());
		DataModuleVo dataModuleVo = this.buildVo(dataModule);
		dataModuleVo.setDataModuleDetailVoList(detailVoList);
		return dataModuleVo;
	}

	private DataModuleVo buildVo(TbDataModule dataModule){
		DataModuleVo dataModuleVo = new DataModuleVo();
		BeanUtils.copyProperties(dataModule, dataModuleVo);
		return dataModuleVo;
	}

	private void checkData(TbDataModule dataModule){
		if (dataModule==null){
			throw new BadRequestException("记录不存在");
		}
	}

	@Transactional
	@Override
	public DataModuleVo updateDataModule(DataModuleDto dataModuleDto){
		TbDataModule dataModule = this.tbDataModuleDao.getDMById(dataModuleDto.getId()) ;
		this.checkData(dataModule);
		if (!CommonEnum.CommonStatusEnum.OK.getCode().equals(dataModule.getStatus())){
			throw new BadRequestException("非生效状态") ;
		}
		BeanUtils.copyProperties(dataModuleDto, dataModule,"tableName");
		this.tbDataModuleDao.save(dataModule);
		List<DataModuleDetailVo> detailVoList=dataModuleDetailService.updateDataModuleDetailList(dataModule.getId(),dataModuleDto.getDataModuleDetailDtoList());
		DataModuleVo dataModuleVo = this.buildVo(dataModule);
		dataModuleVo.setDataModuleDetailVoList(detailVoList);
		return dataModuleVo;
	}

	@Transactional
	@Override
	public void cancelDataModule(Integer id){
		TbDataModule dataModule = this.tbDataModuleDao.getDMById(id) ;
		this.checkData(dataModule);
		if (CommonEnum.CommonStatusEnum.DEL.getCode().equals(dataModule.getStatus())){
			throw new BadRequestException("已是注销状态") ;
		}
		dataModule.setStatus(CommonEnum.CommonStatusEnum.DEL.getCode());
		this.tbDataModuleDao.save(dataModule);
	}

	@Transactional
	@Override
	public void reuseDataModule(Integer id) {
		TbDataModule dataModule = this.tbDataModuleDao.getDMById(id) ;
		this.checkData(dataModule);
		if (!CommonEnum.CommonStatusEnum.DEL.getCode().equals(dataModule.getStatus())){
			throw new BadRequestException("非注销状态") ;
		}
		dataModule.setStatus(CommonEnum.CommonStatusEnum.OK.getCode());
		this.tbDataModuleDao.save(dataModule);
	}

	@Override
	public DataModuleVo getDataModule(Integer id) {
		TbDataModule dataModule = this.tbDataModuleDao.getDMById(id) ;
		this.checkData(dataModule);
		DataModuleVo dataModuleVo = this.buildVo(dataModule);
		dataModuleVo.setDataModuleDetailVoList(this.dataModuleDetailService.findAllByModuleId(id));
		return dataModuleVo;
	}

	@Override
	public DataModuleVo getByTableName(String tableName) {
		TbDataModule dataModule = this.tbDataModuleDao.getByTableName(tableName) ;
		this.checkData(dataModule);
		DataModuleVo dataModuleVo = this.buildVo(dataModule);
		dataModuleVo.setDataModuleDetailVoList(this.dataModuleDetailService.findAllByModuleId(dataModule.getId()));
		return dataModuleVo;
	}

	@Override
	public List<DataModuleVo> queryList(SysRequest<DataModuleDto> dataModuleRequest) {
		Pageable pageable = dataModuleRequest.pageable();
		Page<TbDataModule> page ;
		if (dataModuleRequest.getParamDto()!=null){
			Specification<TbDataModule> specification = new Specification<TbDataModule>() {
				@Override
				@Nullable
				public Predicate toPredicate(@NonNull Root<TbDataModule> root, @NonNull CriteriaQuery<?> criteriaQuery, @NonNull CriteriaBuilder criteriaBuilder) {
					List<Predicate> predicateList = new ArrayList<>();
					if (StrUtil.isNotBlank(dataModuleRequest.getParamDto().getTableName())) {
						Path<String> tableNamePath = root.get("tableName");
						predicateList.add(criteriaBuilder.equal(tableNamePath, dataModuleRequest.getParamDto().getTableName()));
					}
					if (StrUtil.isNotBlank(dataModuleRequest.getParamDto().getName())) {
						Path<String> namePath = root.get("name");
						predicateList.add(criteriaBuilder.like(namePath, "%" + dataModuleRequest.getParamDto().getName() + "%"));
					}
					Path<String> statusPath = root.get("status");
					predicateList.add(criteriaBuilder.equal(statusPath, CommonEnum.CommonStatusEnum.OK.getCode()));
					criteriaQuery.where(predicateList.toArray(new Predicate[0]));
					return criteriaQuery.getRestriction();
				}
			};
			page = this.tbDataModuleDao.findAll(specification, pageable);
		} else {
			page = this.tbDataModuleDao.findAll(pageable);
		}
		List<DataModuleVo> moduleVoList = new ArrayList<>();
		for (TbDataModule dataModule : page.getContent()){
			moduleVoList.add(this.buildVo(dataModule));
		}
		return moduleVoList;
	}


}
